﻿/****************************************************************************
 * Application   : Freekick Desktop Manager
 * Author        : sfreekick
 * Email         : sfreekick@gmail.com
 * Copyright     : (C) 2008 sfreekick
 * **************************************************************************/

/****************************************************************************
 *  This file is part of FreeKickManager.
 *
 *  FreeKickManager is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  FreeKickManager is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with FreeKickManager. If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Xml.Serialization;
using System.Data.Common;
using System.Windows.Forms;

namespace FreeKickManager
{
    public class ActualizadorBaseDatos
    {
        private BDFreeKick bd = null;

        public bool error = false;
        public string msgError = "";

        public ActualizadorBaseDatos(BDFreeKick bd)
        {
            this.bd = bd;
        }

        private bool descargarXmlJugadores(string path)
        {
            bool res = true;

            try
            {
                StreamWriter sw = new StreamWriter(path, false, Encoding.Default, 8192);

                StringBuilder sb = new StringBuilder();

                byte[] buf = new byte[8192];

                string url = "http://www.freekick.org/public/getdata.php?getdata=ownplayers&datatype=xml&username=" + FrmPrincipal.opciones.obtenerOpcion("usuario") + "&password=" + FrmPrincipal.opciones.obtenerOpcion("password");

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                if (FrmPrincipal.opciones.obtenerOpcion("usarProxy").Equals("1"))
                {
                    request.Proxy = new System.Net.WebProxy(FrmPrincipal.opciones.obtenerOpcion("proxyUrl") + ":" + FrmPrincipal.opciones.obtenerOpcion("proxyPuerto"), true);
                    request.Proxy.Credentials = new NetworkCredential(FrmPrincipal.opciones.obtenerOpcion("proxyUsuario"), FrmPrincipal.opciones.obtenerOpcion("proxyPassword"), FrmPrincipal.opciones.obtenerOpcion("proxyDominio"));
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    count = resStream.Read(buf, 0, buf.Length);

                    if (count != 0)
                    {
                        tempString = Encoding.Default.GetString(buf, 0, count);

                        sb.Append(tempString);
                    }
                }
                while (count > 0);

                //Elimino posibles warnings del principio del fichero
                string sbStr = sb.ToString();
                sbStr = sbStr.Substring(sbStr.IndexOf("<?xml version"));

                sw.Write(sbStr);

                sw.Flush();
                sw.Close();
            }
            catch (Exception ex)
            {
                error = true;
                msgError = "Se ha producido un error en la descarga del fichero XML. Detalle del error:\n\n" + ex.Message;

                res = false;
            }

            return res;
        }

        private players cargarXmlJugadores(string path)
        {
            players p = null;

            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(players));

                FileStream fs = new FileStream(path, FileMode.Open);

                p = (players)serializer.Deserialize(fs);

                fs.Close();
            }
            catch (InvalidOperationException)
            {
                MessageBox.Show("El fichero XML descargado no es correcto.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return p;
        }

        public void actualizarDatosDiarios()
        {
            //TODO: Aquí habría que comprobar que no se ha hecho ya la actualización diaria.

            //Descargar el XML con los datos
            bool descargado = descargarXmlJugadores("temp\\jugadores.xml");

            if (descargado)
            {
                //Cargamos el XML con los datos de los jugadores
                players players = cargarXmlJugadores("temp\\jugadores.xml");

                if (players != null)
                {
                    try
                    {
                        bd.comenzarTransaccion();

                        foreach (player p in players.player)
                        {
                            actualizarJugador(p);

                            actualizarEntrenamiento(p);

                            actualizarEstado(p);

                            //TODO: Actualizar datos de estadísticas.
                        }

                        //Actualizamos la fecha de última actualización
                        bd.updateParametro("lastupd", Traductor.traducirFechaTexto(DateTime.Now));

                        bd.finalizarTransaccion();
                    }
                    catch (DbException ex)
                    {
                        error = true;
                        msgError = "Se han producido errores durante la actualización: " + ex.Message;
                    }
                }
            }
        }

        public void actualizarDatosIniciales()
        {
            //Descargamos el XML actual
            bool descargado = descargarXmlJugadores("temp\\jugadores.xml");

            if (descargado)
            {
                //Cargamos el XML con los datos de los jugadores
                players players = cargarXmlJugadores("temp\\jugadores.xml");

                if (players != null)
                {
                    try
                    {
                        bd.comenzarTransaccion();

                        eliminarDatos();

                        foreach (player p in players.player)
                        {
                            actualizarJugador(p);

                            actualizarEstado(p);

                            actualizarEntrenamiento(p);
                        }

                        //Actualizamos la fecha de última actualización
                        bd.updateParametro("lastupd", Traductor.traducirFechaTexto(DateTime.Now));

                        bd.finalizarTransaccion();
                    }
                    catch (DbException ex)
                    {
                        msgError = "Se han producido errores durante la carga: " + ex.Message;
                        error = true;
                    }
                }
            }
        }

        private int actualizarJugador(player p)
        {
            int res;

            Jugador j = new Jugador();

            j.tipo = p.type.Equals("goalkeeper") ? TipoJugador.Portero : TipoJugador.Campo;
            j.nombre = p.name.first;
            j.apellidos = p.name.last.Text[0];
            j.nick = p.name.nick;
            j.años = Convert.ToInt32(p.age.years);
            j.meses = Convert.ToInt32(p.age.months);
            j.dias = Convert.ToInt32(p.age.days);
            j.nacionalidad = p.nation;
            j.juvenil = p.age.youth;
            j.pierna = p.preferred_foot.Equals("right") ? Pierna.Diestro : Pierna.Zurdo;
            j.experiencia = p.experience;
            j.lealtad = p.loyalty;
            j.salario = Convert.ToInt32(p.salary.total);
            j.precioCompra = Convert.ToInt32(p.purchase_price);
            j.fechaEntrada = p.join_date;
            j.id = Convert.ToInt32(p.id);

            //Se intenta el Update
            res = bd.updateJugador(j);

            //Si no se ha podido actualizar --> Jugador Nuevo (Insert)
            if (res == 0)
            {
                res = bd.insertJugador(j);
            }

            return res;
        }

        private int actualizarEntrenamiento(player p)
        {
            int res;

            Jugador j = new Jugador();

            j.id = Convert.ToInt32(p.id);
            j.entrenamiento.modo = p.training.mode.Equals("train") ? ModoEntrenamiento.Normal : ModoEntrenamiento.Forma;
            j.entrenamiento.habilidad1 = Traductor.traducirHabilidad(p.training.skill[0].Text[0]);
            j.entrenamiento.habilidad2 = Traductor.traducirHabilidad(p.training.skill[1].Text[0]);

            //Se intenta el Update
            res = bd.updateEntrenamiento(j);

            //Si no se ha podido actualizar --> Jugador Nuevo (Insert)
            if (res == 0)
            {
                res = bd.insertEntrenamiento(j);
            }

            return res;
        }

        private int actualizarEstado(player p)
        {
            int res = 0;

            Jugador j = new Jugador();

            j.id = Convert.ToInt32(p.id);
            j.estado.fecha = DateTime.Now;
            j.estado.forma = p.form.current;
            j.estado.tendencia = Convert.ToInt32(p.form.trend);
            j.estado.estadofisico = Convert.ToInt32(p.match_readiness.league.ready);

            if (p.type.Equals("goalkeeper"))
            {
                j.estado.actref = Convert.ToInt32(p.skills[0].Items[0]);
                j.estado.potref = Convert.ToInt32(p.skills[0].Items[1]);

                j.estado.actcol = Convert.ToInt32(p.skills[1].Items[0]);
                j.estado.potcol = Convert.ToInt32(p.skills[1].Items[1]);

                j.estado.actint = Convert.ToInt32(p.skills[2].Items[0]);
                j.estado.potint = Convert.ToInt32(p.skills[2].Items[1]);

                j.estado.actct = Convert.ToInt32(p.skills[3].Items[0]);
                j.estado.potct = Convert.ToInt32(p.skills[3].Items[1]);

                j.estado.actorg = Convert.ToInt32(p.skills[4].Items[0]);
                j.estado.potorg = Convert.ToInt32(p.skills[4].Items[1]);
            }
            else if (p.type.Equals("outfielder"))
            {
                j.estado.actrem = Convert.ToInt32(p.skills[0].Items[0]);
                j.estado.potrem = Convert.ToInt32(p.skills[0].Items[1]);

                j.estado.actdes = Convert.ToInt32(p.skills[1].Items[0]);
                j.estado.potdes = Convert.ToInt32(p.skills[1].Items[1]);

                j.estado.actcb = Convert.ToInt32(p.skills[2].Items[0]);
                j.estado.potcb = Convert.ToInt32(p.skills[2].Items[1]);

                j.estado.actpa = Convert.ToInt32(p.skills[3].Items[0]);
                j.estado.potpa = Convert.ToInt32(p.skills[3].Items[1]);

                j.estado.actae = Convert.ToInt32(p.skills[4].Items[0]);
                j.estado.potae = Convert.ToInt32(p.skills[4].Items[1]);

                j.estado.actcon = Convert.ToInt32(p.skills[5].Items[0]);
                j.estado.potcon = Convert.ToInt32(p.skills[5].Items[1]);

                j.estado.actent = Convert.ToInt32(p.skills[6].Items[0]);
                j.estado.potent = Convert.ToInt32(p.skills[6].Items[1]);

                j.estado.actcol = Convert.ToInt32(p.skills[7].Items[0]);
                j.estado.potcol = Convert.ToInt32(p.skills[7].Items[1]);
            }

            res = bd.insertEstado(j);

            return res;
        }

        private int eliminarDatos()
        {
            int res = 0;

            res = bd.deleteJugadores();
            res = bd.deleteEntrenamiento();
            res = bd.deleteEstado();
            res = bd.deleteNotas();

            return res;
        }
    }
}
